#include "SetBrokerSortDlg.h"

#include <core/FileSys.h>
#include <core/ImageMgr.h>
#include <core/StyleMgr.h>
#include <core/time/system_time.h>
#include <uam/ServerTimeMgr.h>
#include <widgets/SImageButton.h>

#include <QApplication>
#include <QDesktopWidget>
#include <QDrag>
#include <QDragEnterEvent>
#include <QFile>
#include <QGridLayout>
#include <QMimeData>
#include <QPushButton>
#include <QSettings>
#include <QStylePainter>
#include <QVBoxLayout>

#include "../BondDataCenter.h"
#include "uam/UserAccountManager.h"

static void getBrokerColor(int id, QColor& st, QColor& end, QString& name) {
  switch (id) {
    case 1: {
      st = StyleMgr::instance().color("BrokerGuoli_L1");
      end = StyleMgr::instance().color("BrokerGuoli_L2");
      name = QObject::tr("国利");
    } break;
    case 2: {
      st = StyleMgr::instance().color("BrokerGuoji_L1");
      end = StyleMgr::instance().color("BrokerGuoji_L2");
      name = QObject::tr("国际");
    } break;
    case 3: {
      st = StyleMgr::instance().color("BrokerZhongcheng_L1");
      end = StyleMgr::instance().color("BrokerZhongcheng_L2");
      name = QObject::tr("中诚");
    } break;
    case 4: {
      st = StyleMgr::instance().color("BrokerPingan_L1");
      end = StyleMgr::instance().color("BrokerPingan_L2");
      name = QObject::tr("平安");
    } break;
    case 5: {
      st = StyleMgr::instance().color("BrokerXintang_L1");
      end = StyleMgr::instance().color("BrokerXintang_L2");
      name = QObject::tr("信唐");
    } break;
    case 6: {
      st = StyleMgr::instance().color("BrokerShangtian_L1");
      end = StyleMgr::instance().color("BrokerShangtian_L2");
      name = QObject::tr("上田");
    } break;
    case 98: {
      st = StyleMgr::instance().color("BrokerSS");
      end = StyleMgr::instance().color("BrokerSS");
      name = QObject::tr("森浦");
    } break;
    case 99: {
      st = qRgb(42, 36, 105);
      end = qRgb(42, 36, 105);
      name = QObject::tr("经纪");
    } break;
    case 101: {
      st = qRgb(148, 70, 55);
      end = qRgb(148, 70, 55);
      name = QObject::tr("经纪");
    } break;
    default:
      break;
  }
}

SetBrokerSortDlg::SetBrokerSortDlg(QWidget* p /*= nullptr*/) : SPopupWindow(p) {
  setTitle(tr("设置经纪商排序"));
  setFixedSize(400, 448);
  getBtnClose()->hide();
  setAcceptDrops(true);

  QDesktopWidget* desk = QApplication::desktop();
  int w = desk->width();
  int h = desk->height();
  this->move((w - width()) / 2, (h - height()) / 2);

  QVBoxLayout* mainLayout = contentLayout();
  QSpacerItem* spItem = new QSpacerItem(0, 16);
  mainLayout->addSpacerItem(spItem);

  QVBoxLayout* textLayout = new QVBoxLayout();
  textLayout->setContentsMargins(0, 0, 0, 0);

  QLabel* brokerSort = new QLabel(
      tr("欢迎使用 qeubee, 您可以对经纪商的排列顺序进行设置。"), this);
  textLayout->addWidget(brokerSort, 0, Qt::AlignHCenter);
  textLayout->addSpacing(7);

  QLabel* brokerSortWay =
      new QLabel(tr("请将经纪商标签拖拽至右侧序列框内"), this);
  brokerSortWay->setStyleSheet(
      QString("color:#%1")
          .arg(StyleMgr::instance().color("Highlight").rgb(), 0, 16));
  textLayout->addWidget(brokerSortWay, 0, Qt::AlignHCenter);
  mainLayout->addLayout(textLayout);

  m_pBtnAddAuto = addBtn(QMessageBox::Apply, tr("一键添加"));
  m_pBtnSave = addBtn(QMessageBox::Ok, tr("保存并退出"));

  QSpacerItem* spGridBefore = new QSpacerItem(0, 23);
  mainLayout->addSpacerItem(spGridBefore);

  QHBoxLayout* hLayout = new QHBoxLayout();
  hLayout->setContentsMargins(38, 0, 0, 15);
  QLabel* broker = new QLabel(tr("经纪商"), this);
  broker->setStyleSheet(
      QString("color:#%1;font-weight:bold;")
          .arg(StyleMgr::instance().color("SupportingWord").rgb(), 0, 16));
  hLayout->addWidget(broker);
  hLayout->addSpacing(25);
  QLabel* sortDisplay = new QLabel(tr("排序显示"), this);
  sortDisplay->setStyleSheet(
      QString("color:#%1;font-weight:bold;")
          .arg(StyleMgr::instance().color("SupportingWord").rgb(), 0, 16));
  hLayout->addWidget(sortDisplay);
  mainLayout->addLayout(hLayout);

  m_gridLayout = new QGridLayout();
  m_gridLayout->setContentsMargins(6, 0, 6, 0);
  m_gridLayout->setSpacing(35);
  m_gridLayout->setVerticalSpacing(16);

  initBrokerSortDlg();
  int nID;
  for (int i = 0; i < m_nEnableBroker; i++) {
    nID = m_stlBeSort[i];
    if (!CBrokerList::IsValidBroker(nID)) {
      SLabel* beSort = new SLabel(this, kEmpty);
      beSort->setFixedSize(120, 24);
      beSort->setIndex(i);
      m_gridLayout->addWidget(beSort, i, 0);
    } else {
      SLabel* broker = new SLabel(this, kBroker, nID);
      broker->setFixedSize(120, 24);
      broker->setIndex(i);
      m_gridLayout->addWidget(broker, i, 0);
    }
  }
  for (int i = 0; i < m_nEnableBroker; i++) {
    nID = m_stlSortShow[i];
    if (!CBrokerList::IsValidBroker(nID)) {
      SLabel* sortShow = new SLabel(this, kNumber);
      sortShow->setFixedSize(120, 24);
      sortShow->paintNumber(i + 1);
      sortShow->setIndex(i + m_nEnableBroker);
      m_gridLayout->addWidget(sortShow, i, 2);
    } else {
      SLabel* broker = new SLabel(this, kBroker, nID);
      broker->setFixedSize(120, 24);
      broker->setIndex(i + m_nEnableBroker);
      m_gridLayout->addWidget(broker, i, 2);
    }
  }
  mainLayout->addLayout(m_gridLayout);
  connect(m_pBtnAddAuto, &QPushButton::clicked, this,
          &SetBrokerSortDlg::onAddButtonAuto);
  connect(m_pBtnSave, &QPushButton::clicked, this,
          &SetBrokerSortDlg::onSaveAndExit);
}

void SetBrokerSortDlg::initBrokerSortDlg() {
  const CBrokerList& m_brokerList =
      SSUserAccountManager::instance().GetReadonlyBroker();
  std::vector<int> sortid = m_brokerList.GetSortKey();

  m_nEnableBroker = 0;
  CBrokerList::BrokerMap::const_iterator itBk;
  const CBrokerList& brokerlist = m_brokerList;
  std::vector<int> vctBroker;
  for (itBk = brokerlist.GetBrokerMap().begin();
       itBk != brokerlist.GetBrokerMap().end(); itBk++) {
    if (CBrokerList::IsValidBroker(itBk->first) &&
        (itBk->second.m_enableFlag_BOND || itBk->second.m_enableFlag_NCD)) {
      vctBroker.push_back(itBk->first);
    }
  }

  const std::vector<int>& vctSort = m_brokerList.GetSortKey();
  for (std::vector<int>::const_iterator itSort = vctSort.begin();
       itSort != vctSort.end(); itSort++) {
    int nSort = *itSort;
    itBk = brokerlist.GetBrokerMap().find(nSort);
    if (brokerlist.GetBrokerMap().end() == itBk) continue;
    if (CBrokerList::IsValidBroker(itBk->first) &&
        (itBk->second.m_enableFlag_BOND || itBk->second.m_enableFlag_NCD)) {
      m_nEnableBroker++;
      m_stlBeSort.push_back(itBk->first);
      m_stlSortShow.push_back(-1);
      std::vector<int>::iterator it =
          std::find(vctBroker.begin(), vctBroker.end(), itBk->first);
      if (it != vctBroker.end()) {
        vctBroker.erase(it);
      }
    }
  }

  if (m_brokerList.IsSaveSortId()) {
    m_stlSortShow = m_stlBeSort;
    for (size_t i = 0; i < m_stlBeSort.size(); ++i) {
      m_stlBeSort[i] = -1;
    }
    m_pBtnAddAuto->setEnabled(false);
    m_pBtnSave->setEnabled(true);
  } else {
    if (m_stlBeSort.size() > 1) {
      int nId = m_stlBeSort[0];
      m_stlBeSort.erase(m_stlBeSort.begin());
      m_stlBeSort.push_back(nId);
    }
    m_pBtnAddAuto->setEnabled(true);
    m_pBtnSave->setEnabled(false);
  }
}

void SetBrokerSortDlg::saveGlobalSettingConfig() {
  QSettings settings(
      FileSys::instance()->writeableAppCfgDir() + "/globalsettings.ini",
      QSettings::IniFormat);
  settings.beginGroup("User");
  settings.setValue("FirstRun", true);
  settings.setValue("FirstRunValid", m_sztime);
  settings.endGroup();
}

void SetBrokerSortDlg::paintEvent(QPaintEvent* event) {
  SPopupWindow::paintEvent(event);
  QStylePainter painter(this);

  QLineF line(200, 110, 200, 390);
  painter.setPen(StyleMgr::instance().color("BorderNormal"));
  painter.drawLine(line);
}

void SetBrokerSortDlg::mousePressEvent(QMouseEvent* event) {
  SLabel* child = dynamic_cast<SLabel*>(childAt(event->pos()));
  if (!child || child->getSLabelStatus() != kBroker) return;

  QLayoutItem* gridLabel = nullptr;
  QRect beSortRect, sortShowRect;
  if (m_bSavePos == false) {
    for (int i = 0; i < m_nEnableBroker; i++) {
      gridLabel = m_gridLayout->itemAtPosition(i, 0);
      beSortRect = gridLabel->widget()->frameGeometry();
      m_beSortRectMap.insert(std::pair<int, QRect>(i, beSortRect));

      gridLabel = m_gridLayout->itemAtPosition(i, 2);
      sortShowRect = gridLabel->widget()->frameGeometry();
      m_sortShowRectMap.insert(std::pair<int, QRect>(i, sortShowRect));
    }
    m_bSavePos = true;
  }

  QDrag* drag = new QDrag(this);
  QPixmap pixmap = child->grab();

  int MousePressIndex = child->getIndex();

  if (m_stlBeSort[MousePressIndex % m_nEnableBroker] != -1 ||
      m_stlSortShow[MousePressIndex % m_nEnableBroker] != -1)
    m_nDragIndex = MousePressIndex;

  QByteArray itemData;
  QDataStream dataStream(&itemData, QIODevice::WriteOnly);
  QPoint hotSpot = event->pos() - child->pos();
  QPoint originPos = event->pos();

  BrokerStatus childSlabelStatus = child->getSLabelStatus();
  int childBrokerId = child->getBrokerId();

  dataStream << MousePressIndex << childSlabelStatus << childBrokerId;
  QMimeData* mimeData = new QMimeData;
  mimeData->setData("application/x-dnditemdata", itemData);
  drag->setMimeData(mimeData);
  drag->setPixmap(pixmap);
  drag->setHotSpot(hotSpot);
  bool hasChanged = false;
  // 拖动时改变点击的Label
  if (m_nDragIndex < m_nEnableBroker) {
    child->changeLabelType(kEmpty);
  } else {
    int num = m_nDragIndex % m_nEnableBroker;
    child->paintNumber(num + 1);
    child->changeLabelType(kNumber);
  }

  if (drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction) !=
      Qt::MoveAction) {  // 如果是drop到窗口外，就恢复原先label的样式
    child->changeLabelType(childSlabelStatus, childBrokerId);
  }
}

void SetBrokerSortDlg::dragEnterEvent(QDragEnterEvent* event) {
  if (event->mimeData()->hasFormat("application/x-dnditemdata")) {
    if (event->source() == this) {
      event->setDropAction(Qt::MoveAction);
      event->accept();
    } else {
      event->acceptProposedAction();
    }
  } else {
    event->ignore();
  }
}

void SetBrokerSortDlg::dropEvent(QDropEvent* event) {
  if (event->mimeData()->hasFormat("application/x-dnditemdata")) {
    QByteArray itemData = event->mimeData()->data("application/x-dnditemdata");
    QDataStream dataStream(&itemData, QIODevice::ReadOnly);

    BrokerStatus mousePressLabelType;
    int mousePressBrokerId, MousePressIndex, col, row;
    dataStream >> MousePressIndex >> mousePressLabelType >> mousePressBrokerId;
    SLabel* dropChild = dynamic_cast<SLabel*>(childAt(event->pos()));

    if (MousePressIndex >= m_nEnableBroker) {
      row = MousePressIndex % m_nEnableBroker;
      col = 2;
    } else {
      row = MousePressIndex;
      col = 0;
    }

    QLayoutItem* lastMPGrid = m_gridLayout->itemAtPosition(row, col);
    SLabel* lastMousePressLabel = dynamic_cast<SLabel*>(lastMPGrid->widget());

    if (dropChild != nullptr) {
      if (MousePressIndex == dropChild->getIndex()) return;

      for (int i = 0; i < m_nEnableBroker; i++) {
        if (m_beSortRectMap[i].contains(event->pos())) {
          int nID;
          if (m_nDragIndex < m_nEnableBroker) {
            nID = m_stlBeSort[m_nDragIndex];
            m_stlBeSort[m_nDragIndex] = m_stlBeSort[i];
          } else {
            nID = m_stlSortShow[m_nDragIndex % m_nEnableBroker];
            m_stlSortShow[m_nDragIndex % m_nEnableBroker] = m_stlBeSort[i];
          }
          m_stlBeSort[i] = nID;
        }
      }
      for (int i = 0; i < m_nEnableBroker; i++) {
        if (m_sortShowRectMap[i].contains(event->pos())) {
          int nID;
          if (m_nDragIndex < m_nEnableBroker) {
            nID = m_stlBeSort[m_nDragIndex];
            m_stlBeSort[m_nDragIndex] = m_stlSortShow[i];
          } else {
            nID = m_stlSortShow[m_nDragIndex % m_nEnableBroker];
            m_stlSortShow[m_nDragIndex % m_nEnableBroker] = m_stlSortShow[i];
          }
          m_stlSortShow[i] = nID;
        }
      }

      if (dropChild->getSLabelStatus() == kBroker) {
        int dropBrokerId = dropChild->getBrokerId();
        dropChild->changeLabelType(kBroker, mousePressBrokerId);
        lastMousePressLabel->changeLabelType(kBroker, dropBrokerId);
      } else {
        if (m_nDragIndex < m_nEnableBroker) {
          dropChild->changeLabelType(kBroker, mousePressBrokerId);
        } else {
          dropChild->changeLabelType(kBroker, mousePressBrokerId);
        }
      }
    } else {
      lastMousePressLabel->changeLabelType(mousePressLabelType,
                                           mousePressBrokerId);
    }

    if (m_hoveredLabel != nullptr) {
      if (m_hoveredLabel->getSLabelStatus() != kBroker &&
          m_hoveredLabel->getSLabelStatus() != kEmpty)
        m_hoveredLabel->setHovered(false);
    }
    bool allSort = true;
    bool allNoSort = true;
    for (int i = 0; i < m_nEnableBroker; i++) {
      if (m_stlBeSort[i] != -1)
        allSort = false;
      else
        allNoSort = false;
    }
    m_pBtnAddAuto->setEnabled(allNoSort);
    m_pBtnSave->setEnabled(allSort);

    if (event->source() == this) {
      event->setDropAction(Qt::MoveAction);
      event->accept();
    } else {
      event->acceptProposedAction();
    }
  } else {
    event->ignore();
  }
}

void SetBrokerSortDlg::dragMoveEvent(QDragMoveEvent* event) {
  if (event->mimeData()->hasFormat("application/x-dnditemdata")) {
    if (event->source() == this) {
      event->setDropAction(Qt::MoveAction);
      QByteArray itemData =
          event->mimeData()->data("application/x-dnditemdata");
      QDataStream dataStream(&itemData, QIODevice::ReadOnly);
      int MousePressIndex;
      dataStream >> MousePressIndex;
      SLabel* child = dynamic_cast<SLabel*>(childAt(event->pos()));
      if (child != nullptr) {
        if (MousePressIndex != child->getIndex() &&
            child->getSLabelStatus() != kBroker &&
            child->getSLabelStatus() != kEmpty) {
          for (int i = 0; i < m_nEnableBroker; i++) {
            if (m_sortShowRectMap[i].contains(event->pos())) {
              child->setHovered(true);
              if (m_hoveredLabel != child) {
                if (m_hoveredLabel) m_hoveredLabel->setHovered(false);
                m_hoveredLabel = child;
              }
              break;
            }
          }
        }
      } else if (m_hoveredLabel != nullptr) {
        m_hoveredLabel->setHovered(false);
      }
      event->accept();
    } else {
      event->acceptProposedAction();
    }
  } else {
    event->ignore();
  }
}

void SetBrokerSortDlg::onAddButtonAuto() {
  QLayoutItem *gridLeftabel = nullptr, *gridRightLabel = nullptr;
  for (int i = 0; i < m_nEnableBroker; i++) {
    m_stlSortShow[i] = m_stlBeSort[i];
    m_stlBeSort[i] = -1;
  }
  for (int i = 0; i < m_nEnableBroker; i++) {
    gridLeftabel = m_gridLayout->itemAtPosition(i, 0);
    SLabel* SortDoneLabel = dynamic_cast<SLabel*>(gridLeftabel->widget());
    m_stlSaveId.push_back(SortDoneLabel->getBrokerId());
    SortDoneLabel->changeLabelType(kEmpty, -1);
  }
  for (int i = 0; i < m_nEnableBroker; i++) {
    gridRightLabel = m_gridLayout->itemAtPosition(i, 2);
    SLabel* showLabel = dynamic_cast<SLabel*>(gridRightLabel->widget());
    showLabel->changeLabelType(kBroker, m_stlSaveId[i]);
  }

  m_pBtnAddAuto->setEnabled(false);
  m_pBtnSave->setEnabled(true);
}

void SetBrokerSortDlg::onSaveAndExit() {
  for (int i = 0; i < m_nEnableBroker; i++) {
    if (m_stlBeSort[i] != -1) {
      QMessageBox::information(nullptr, tr("提示"), tr("请完成经纪商排序!"));
      return;
    }
  }

  qb::base::CTime ct(ServerTimeMgr::instance().serverTime());
  int nCurTime = ct.GetYear() * 100 + ct.GetMonth();
  m_sztime = nCurTime;

  saveGlobalSettingConfig();

  BondDataCenter::instance().requestQBCompanySort(m_nEnableBroker,
                                                  m_stlSortShow);

  close();
}

SLabel::SLabel(QWidget* parent /*= nullptr */, BrokerStatus type /*= kEmpty*/,
               int brokerId /*= -1*/)
    : QLabel(parent) {
  m_type = type;
  m_brokerId = brokerId;
  getBrokerColor(m_brokerId, m_st, m_end, m_txt);
  applyStyleSheet();
}

SLabel::~SLabel() {}

void SLabel::applyStyleSheet() {
  if (m_type == kEmpty) {
    m_styleSheet =
        QString("border:1px solid #%1;border-radius:2px;background-color:#%2;")
            .arg(StyleMgr::instance().color("BorderNormal").rgb(), 0, 16)
            .arg(StyleMgr::instance().color("BackNormal").rgb(), 0, 16);
  } else if (m_type == kNumber) {
    m_styleSheet =
        QString(
            "SLabel			{border:1px solid "
            "#%1;border-radius:2px;background-color:#%2;}"
            "SLabel[beHoverd=\"true\"]{background-color:#%3;}"
            //"SLabel[beHoverd=\"false\"]{background-color:#%2;}"
            )
            .arg(StyleMgr::instance().color("BorderNormal").rgb(), 0, 16)
            .arg(StyleMgr::instance().color("BackNormal").rgb(), 0, 16)
            .arg(StyleMgr::instance().color("Hover").rgb(), 0, 16);
  } else {
    if (m_st == nullptr || m_end == nullptr) return;
    m_styleSheet =
        QString(
            "border-radius:2px;font:bold;background-color:qlineargradient(x1:0,"
            " y1:0, x2:0, y2:1,stop:0 #%1,stop:1 #%2);")
            .arg(m_st.rgb(), 0, 16)
            .arg(m_end.rgb(), 0, 16);
  }
  setStyleSheet(m_styleSheet);
}

void SLabel::changeLabelType(BrokerStatus type, int brokerId) {
  m_type = type;
  m_brokerId = brokerId;
  if (m_brokerId != -1) getBrokerColor(m_brokerId, m_st, m_end, m_txt);
  applyStyleSheet();
  update();
}

void SLabel::setHovered(bool hovered) {
  if (hovered) {
    setProperty("beHoverd", "true");
  } else {
    setProperty("beHoverd", "false");
  }
  applyStyleSheet();
}

void SLabel::paintEvent(QPaintEvent* e) {
  QLabel::paintEvent(e);

  QRect r = rect();
  QStylePainter painter(this);
  QRect NumRect;
  QFont f = font();

  if (m_type == kNumber) {
    painter.setPen(StyleMgr::instance().color("SupportingWord"));
    f.setBold(true);

    QFontMetrics fm(font());
    QString num = QString("%1").arg(m_paintNum);
    int widthNu = fm.horizontalAdvance(num);
    int NumX = r.x() + 8;
    NumRect.setRect(NumX, r.y(), widthNu, r.height());
    painter.setFont(f);
    painter.drawText(NumRect, num,
                     QTextOption(Qt::AlignLeft | Qt::AlignVCenter));
  } else if (m_type == kBroker) {
    painter.setPen(StyleMgr::instance().color("ContactBlack"));
    f.setBold(true);
    QFontMetrics fm(font());
    QString txt = m_txt;
    int widthNu = fm.horizontalAdvance(txt);
    int singleWidth = widthNu / 2;
    int NumX = r.center().x() - singleWidth;
    NumRect.setRect(NumX, r.y(), widthNu, r.height());
    painter.drawText(NumRect, txt, QTextOption(Qt::AlignVCenter));
  }
}
